use crate::core::global_args::Args;
use include_dir::Dir;
use serde_json::json;
use std::fs;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

pub mod global_args;

pub fn generate_source(dir: &Dir, args: &Args) -> anyhow::Result<()> {
    let project_name = args.name.clone();
    for entry in dir.entries() {
        if let Some(x) = entry.as_dir() {
            generate_source(x, args)?;
        } else {
            let file_path = entry.path();
            let mut output_path_buf = PathBuf::new();
            output_path_buf.push(&project_name);
            output_path_buf.push(file_path);
            let output_path = output_path_buf.to_str().unwrap();
            let parent_dir = std::path::Path::new(output_path).parent().unwrap();
            fs::create_dir_all(parent_dir)?;
            let mut file = File::create(output_path)?;
            if let Some(content) = entry.as_file().unwrap().contents_utf8() {
                //替换文字
                let new_content = resolve_template(content, &args);
                if new_content.is_err() {
                    let error = new_content.err().unwrap();
                    let err_msg = error.to_string();
                    let msg = format!("模板解析失败, path:{output_path}, msg:{err_msg}");
                    return Err(anyhow::anyhow!("{}", msg));
                }
                let new_content = new_content?;
                file.write_all(new_content.as_bytes())?;
            } else {
                file.write_all(entry.as_file().unwrap().contents())?;
            }
        }
    }
    Ok(())
}

fn resolve_template(content: &str, template: &Args) -> anyhow::Result<String> {
    let mut engine = upon::Engine::new();
    engine.add_template("source", content)?;
    // engine.add_filter("date_filter", upon_date_filter);
    // engine.add_filter("message_filter", upon_message_filter);
    let template_value = json!(template); // 将template转换为serde_json::Value
    let result = engine
        .template("source")
        .render(upon::value! {template: &template_value})
        .to_string()?;
    Ok(result)
}
